package mapx

func WalkMap(a map[string]interface{}, f func(parent map[string]interface{}, key string, val interface{}) error) error {
	for key, val := range a {
		err := f(a, key, val)
		if err != nil {
			return err
		}
		switch v := val.(type) {
		case map[string]interface{}:
			errWalk := WalkMap(v, f)
			if errWalk != nil {
				return errWalk
			}
		default:
		}
		return nil
	}
	return nil
}

// 过滤掉nil值的字段
func FilterMapNotNil(a map[string]interface{}) map[string]interface{} {
	return FilterMap(a, func(parent map[string]interface{}, key string, val interface{}) bool {
		if val == nil {
			return true
		}
		switch v := val.(type) {
		case map[string]interface{}:
			return v == nil
		}
		return false
	})
}

// 过滤掉default值的字段
func FilterMapNotDefault(a map[string]interface{}) map[string]interface{} {
	return FilterMap(a, func(parent map[string]interface{}, key string, val interface{}) bool {
		if val == nil {
			return true
		}
		switch v := val.(type) {
		case []interface{}:
			return len(v) == 0
		case map[string]interface{}:
			return len(v) == 0
		case string:
			return v == ""
		case bool:
			return v == false
		case int:
			return v == 0
		case int8:
			return v == 0
		case int16:
			return v == 0
		case int32:
			return v == 0
		case int64:
			return v == 0
		case uint:
			return v == 0
		case uint8:
			return v == 0
		case uint16:
			return v == 0
		case uint32:
			return v == 0
		case uint64:
			return v == 0
		case float32:
			return v == 0.0
		case float64:
			return v == 0.0
		}
		return false
	})
}

// f 返回true表示需要过滤掉
func FilterMap(a map[string]interface{}, f func(parent map[string]interface{}, key string, val interface{}) bool) map[string]interface{} {
	result := map[string]interface{}{}
	for key, val := range a {
		过滤掉 := f(a, key, val)
		if 过滤掉 {
			continue
		}
		if val == nil {
			result[key] = nil
		} else {
			switch v := val.(type) {
			case map[string]interface{}:
				m := FilterMap(v, f)
				if len(m) > 0 {
					result[key] = m
				}
			case []interface{}:
				arr := CloneArray(v)
				if len(arr) > 0 {
					result[key] = arr
				}
			default:
				result[key] = v
			}
		}
	}

	return result
}
